package boardgamer.common;

import boardgamer.common.annotations.Immutable;
import com.google.common.base.Objects;

import java.io.Serializable;

import static com.google.common.base.Preconditions.checkNotNull;


/**
 * Contains a pair of GameUpdate and the resulting GameState
 *
 * @author garysoed
 */
@Immutable
public class GameUpdate<GS extends GameState, C extends GameStateChange> implements Serializable {

  private static final long serialVersionUID = -1025061448814881247L;

  private final C stateChange;
  private final GS endState;
  
  /**
   * @param stateChange null for initial game state
   * @param endState    the game state as a result of the state change
   */
  public GameUpdate(C stateChange, GS endState) {
    this.stateChange = stateChange;
    this.endState = checkNotNull(endState, "endState");
  }

  public C getStateChange() {
    return stateChange;
  }

  public GS getEndState() {
    return endState;
  }

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof GameUpdate<?, ?>)) {
      return false;
    }

    GameUpdate<?, ?> that = (GameUpdate<?, ?>) obj;
    return Objects.equal(this.stateChange, that.stateChange)
        && Objects.equal(this.endState, that.endState);
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(stateChange, endState);
  }

  @Override
  public String toString() {
    return Objects.toStringHelper(this)
        .add("stateChange", stateChange)
        .add("endState", endState)
        .toString();
  }
}
